package com.gin.fanbox.call;

import com.fasterxml.jackson.databind.JavaType;
import com.gin.fanbox.callback.FanboxCallback;
import com.gin.fanbox.response.BaseResponse;
import com.gin.fanbox.utils.JacksonUtils;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;
import okhttp3.ResponseBody;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.IOException;
import java.util.function.Function;

/**
 * @author bx002
 * @since 2024/2/5 14:56
 */
public class FanboxCall<T> {
    /**
     * 请求会话
     */
    private final Call call;
    /**
     * 转换器
     */
    private final Function<ResponseBody, T> converter;
    /**
     * 响应类型
     */
    private final Class<T> responseClass;

    public FanboxCall(Call call, Class<T> responseClass) {
        this(call, responseClass, null);
    }

    public FanboxCall(Call call, Class<T> responseClass, @Nullable Function<ResponseBody, T> converter) {
        this.call = call;
        this.responseClass = responseClass;
        this.converter = converter != null ? converter : responseBody -> {
            try {
                final JavaType javaType = JacksonUtils.obtainJavaType(BaseResponse.class, responseClass);
                BaseResponse<T> response = JacksonUtils.MAPPER.readValue(responseBody.byteStream(), javaType);
                final String error = response.getError();
                if (error != null && !error.isEmpty()) {
                    throw new IOException(error);
                }
                return response.getBody();
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        };
    }

    /**
     * 发起同步请求
     *
     * @return 响应
     */
    public T execute() throws IOException {
        try (Response response = call.execute()) {
            final ResponseBody body = response.body();
            return converter.apply(body);
        }
    }

    /**
     * 异步请求
     *
     * @param callback 回调
     */
    public void enqueue(FanboxCallback<T> callback) {
        call.enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                callback.onFailure(call, e);
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                final T res = converter.apply(response.body());
                callback.onSuccess(call, res);
            }
        });
    }
}
